﻿namespace NJQuery {
	using System;
	using System.Web.UI;

	/// <summary>
	/// Uses <see cref="UserControl"/> to provide a standard base implementation of the <see cref="IManagedControl"/> contract requried by the <see cref="Manager"/> control to generate jQuery/JavaScript in addition to HTML markup typical of a control.
	/// </summary>
	public abstract class ManagedUserControl : UserControl, IManagedControl {


		#region Fields

		private HtmlTextWriterTag outerTag;

		#endregion


		#region Constructors

		/// <summary>
		/// Initializes a new instance of the <see cref="ManagedUserControl"/> base class.
		/// </summary>
		protected ManagedUserControl() : this(HtmlTextWriterTag.Div) { }

		/// <summary>
		/// Initializes a new instance of the <see cref="ManagedUserControl"/> base class, providing the main tag to be rendered to the client.
		/// </summary>
		/// <param name="outerTag">The HTML tag to be rendered to the client by this server control.</param>
		protected ManagedUserControl(HtmlTextWriterTag outerTag) {
			this.outerTag = outerTag;
		}

		#endregion


		#region Properties

		protected virtual HtmlTextWriterTag OuterTagKey {
			get { return outerTag; }
		}

		protected virtual string OuterTagName {
			get { return OuterTagKey.ToString(); }
		}

		protected virtual bool VisibilityHiddenOnRender {
			get { return false; }
		}

		protected virtual bool DisplayNoneOnRender {
			get { return false; }
		}

		#endregion


		#region Methods: Overrideable empty implementation of IManagedControl

		/// <summary>
		/// Renders the jQuery "Ready Event" script required to generate the client-side jQuery widget.
		/// This method is used primarily by control developers.
		/// </summary>
		/// <param name="script">A <see cref="ScriptBuilder"/> that creates the output stream to render jQuery JavaScript on the client.</param>
		protected virtual void RenderReadyScript(ScriptBuilder script) { }

		/// <summary>
		/// Renders a script to be executed on page startup.
		/// This method is used primarily by control developers.
		/// </summary>
		/// <param name="script">A <see cref="ScriptBuilder"/> that creates the output stream to render jQuery JavaScript on the client.</param>
		protected virtual void RenderStartupScript(ScriptBuilder script) { }

		/// <summary>
		/// Renders a script to be executed on form/postback submit.
		/// This method is used primarily by control developers.
		/// </summary>
		/// <param name="script">A <see cref="ScriptBuilder"/> that creates the output stream to render jQuery JavaScript on the client.</param>
		protected virtual void RenderSubmitScript(ScriptBuilder script) { }

		#endregion


		#region Methods: Rendering

		/// <summary>
		/// Raises the <see cref="Control.PreRender"/> event.
		/// </summary>
		/// <param name="e">The <see cref="EventArgs"/> object that contains the event data.</param>
		protected override void OnPreRender(EventArgs e) {

			//TODO: Find out if this can be moved to after the base call to make it later...
			Register(Manager.GetCurrent(Page));

			base.OnPreRender(e);
		}

		/// <summary>
		/// Allows a jQuery server control to reference scripts and stylesheets necessary to render their client markup and widgets.
		/// </summary>
		/// <param name="manager">The <see cref="Manager"/> used to handle style and script referencing in addition to unified generation of load and ready scripts.</param>
		protected virtual void Register(Manager manager) { }

		protected override void Render(HtmlTextWriter writer) {

			writer.AddAttribute(HtmlTextWriterAttribute.Id, ClientID);
			if(VisibilityHiddenOnRender) writer.AddStyleAttribute(HtmlTextWriterStyle.Visibility, "hidden");
			if(DisplayNoneOnRender) writer.AddStyleAttribute(HtmlTextWriterStyle.Display, "none");
			writer.RenderBeginTag(OuterTagName);
	
			base.Render(writer);

			writer.RenderEndTag();
	
		}

		#endregion


		#region Explicit implementation: IManagedControl

		void IManagedControl.RenderReadyScript(ScriptBuilder script) {
			RenderReadyScript(script);
		}

		void IManagedControl.RenderStartupScript(ScriptBuilder script) {
			RenderStartupScript(script);
		}

		void IManagedControl.RenderSubmitScript(ScriptBuilder script) {
			RenderSubmitScript(script);
		}

		#endregion


	}

}